#!/usr/bin/perl
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
#  
#  
# Licensed Materials - Property of IBM 
#  
# (C) COPYRIGHT International Business Machines Corp. 2002,2004 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 
# @(#)40   1.33   src/csm/install/uninstallms.perl, setup, csm_rameh, rameh0431a 6/30/04 22:24:18

#--------------------------------------------------------------------------------

=head1    uninstallms.perl

        Development notes:

        The html view of the pod headers in this file can be updated
        by running the command:  

                  tidypod <filename>

	The html veiw of the pod headers will be in the file ./<filename>.html
	and can be viewed with a browser.

	The tidy formatted file will be in <filename>.tdy

	Be sure to run tidypod and copy the .tdy file to <filename> before checking
	in changes.

=cut

#--------------------------------------------------------------------------------

use strict;

BEGIN { $::csmpm = $ENV{'CSM_PM'} ? $ENV{'CSM_PM'} : '/opt/csm/pm'; }

use lib $::csmpm;
use Getopt::Std;
use NodeUtils;
use CSMDefs;
use InstallUtils;

# sets local scope - we only want classes on the Managment Server
# though it's not clear that classes are being used ...?

$ENV{'CT_MANAGEMENT_SCOPE'} = 1;

# message service
$::MSGCAT     = 'csmInstall.cat';
$::MSGMAPPATH = $ENV{'CSM_MSGMAPS'} ? $ENV{'CSM_MSGMAPS'} : '/opt/csm/msgmaps';
$::MSGSET     = 'csminstall';

#--------------------------------------------------------------------------------

=head3	initialize	

        Notes:	globals only

	get the definitions we need for this command 
	in this case get_OSDefs uses the attrs of the management 
	server to identify the correct definitions

=cut

#--------------------------------------------------------------------------------

sub initialize
{

    # setup the global os define variables
    InstallUtils->get_OSDefs();

    @::My_NodeList    = ();
    $::rsct_basic_Flg = 0;
    $::csm_client_Flg = 0;

    # gather the variables
    $::ATTRS{'InstallCSMVersion'} = InstallUtils->get_CSMVersion("csm\.core");
    $::ATTRS{'InstallOSName'}     = InstallUtils->get_OSName;
    $::ATTRS{'InstallDistributionName'}    = InstallUtils->get_DistributionName;
    $::ATTRS{'InstallDistributionVersion'} =
      InstallUtils->get_DistributionVersion;
    $::ATTRS{'InstallPkgArchitecture'} = InstallUtils->get_PkgArchitecture;

    $::osTypeVersion =
        $::ATTRS{'InstallOSName'}
      . $::ATTRS{'InstallDistributionName'}
      . $::ATTRS{'InstallDistributionVersion'};

    #
    # get the appropriate lists of filesets/packages
    #
    # for the management server
    %::Svrpkgdefs =
      InstallUtils->get_pkgdefs(
                                $::ATTRS{'InstallOSName'},
                                $::ATTRS{'InstallDistributionName'},
                                $::ATTRS{'InstallDistributionVersion'},
                                $::ATTRS{'InstallPkgArchitecture'},
                                "MgmtServer",
                                $::ATTRS{'InstallCSMVersion'}
                                );

    # get the list of log files
    @::csm_logfilelist = (@{$::Svrpkgdefs{logfiles}});

    # get the CSM uninstall list
    @::csm_uninstall_packages = (@{$::Svrpkgdefs{csm_unpackages}});
    @::csm_uninstall_packages = reverse @::csm_uninstall_packages;

    # get the rsct uninstall list
    @::rsct_uninstall_packages = (@{$::Svrpkgdefs{rsct_unpackages}});
    @::rsct_uninstall_packages = reverse @::rsct_uninstall_packages;

    # get the list of uninstall directories
    @::csmUninstallList_Directories = (@{$::Svrpkgdefs{csm_uninstall_dirs}});

    # get list of packages that shouldn't be uninstalled
    @::csmUninstallList_Packages = (@{$::Svrpkgdefs{csm_nouninstall_pkgs}});

    if (!defined $::HAMODE)
    {
        my $outref =
          NodeUtils->runrmccmd('lsrsrc-api', "-i", "-s IBM.DmsCtrl::::HAMode");
        $::HAMODE = $$outref[0];
    }
    if($::HAMODE != 0){ #cant run uninstallms 
      NodeUtils->messageFromCat('hams.cat', $::MSGMAPPATH, 'hams', 'E1', 'EMsgUninstallms', $::HAMODE);
    }

}

#--------------------------------------------------------------------------------

=head3	usage	

        Notes:

=cut

#--------------------------------------------------------------------------------

sub usage
{

    NodeUtils->message('I', 'IMsguninstallmsUsage');
    exit 1;
}

#--------------------------------------------------------------------------------

=head3	getArgs	

        Notes:

=cut

#--------------------------------------------------------------------------------

sub getArgs
{
    if (!getopts('fuvVh')) { &usage; }

    if ($::opt_h) { &usage }
    if ($::opt_v) { $::VERBOSE = $::opt_v; }
    if ($::opt_V) { $::VERBOSE = $::opt_V; }

    # check if the Machine is Management Server
    if (!NodeUtils->isMgmtSvr())
    {
        NodeUtils->message('E2', 'EMsgNOManagementServer');
    }

    if ((!($::opt_f)) && ($::opt_u))
    {
        NodeUtils->message('P', 'IMsgUNINSTALLMS_VERIFY_U');
        my $input = getc;
        if (($input !~ /^y/) and ($input !~ /^Y/))
        {
            NodeUtils->message('I', 'IMsgUNINSTALLMS_NOT_UNINSTALLING');
            exit 0;
        }
    }

    if ((!($::opt_f)) && (!($::opt_u)))
    {
        NodeUtils->message('P', 'IMsgUNINSTALLMS_VERIFY');
        my $input = getc;
        if (($input !~ /^y/) and ($input !~ /^Y/))
        {
            NodeUtils->message('I', 'IMsgUNINSTALLMS_NOT_UNINSTALLING');
            exit 0;
        }
    }

}

#--------------------------------------------------------------------------------

=head3	remove_files_dir	

        Notes:

=cut

#--------------------------------------------------------------------------------

sub remove_files_dir
{
    my ($file_name, undef) = @_;
    NodeUtils->runcmd("$::RM -rf $file_name", -1);
    if ($::RUNCMD_RC != 0)
    {
        NodeUtils->message('W', 'EMsgCannotDelete', $file_name);
    }
}

#--------------------------------------------------------------------------------

=head3	check_valid_sisdir

        Notes:

	Check whether the specified directory looks like an SIS directory 

	return:
		0 for false 
		1 for true

=cut

#--------------------------------------------------------------------------------

sub check_valid_sisdir
{
    my ($sisdir) = @_;
    my @sis_subdir = ("images", "scripts", "overrides");

    if (!(-d $sisdir) || (-l $sisdir))
    {
        return 0;
    }

    foreach my $subdir (@sis_subdir)
    {
        return 0 if (!(-d $sisdir . "/" . $subdir));
    }
    return 1;
}

#--------------------------------------------------------------------------------

=head3	move_sis_directory	

        Notes:

=cut

#--------------------------------------------------------------------------------

sub move_sis_directory
{
    my ($sis_csmdir, $sis_origdir);
    my ($cmd,        $rc);
    $sis_csmdir  = "/var/lib/systemimager";
    $sis_origdir = "/csminstall/Linux/SIS";
    my $sis_origdir_back = $sis_origdir . ".csmback";
    my $sis_csmdir_back  = $sis_csmdir . ".csmback";

    # if /csminstall/Linux/SIS directory doesn't exist, there must be
    # something wrong while install SIS packages
    if (!(-d $sis_origdir))
    {
        NodeUtils->message('E', 'EMsgERROR_INSTALLED_SIS');
        return -1;
    }

    if (check_valid_sisdir($sis_csmdir))
    {
        if (-l $sis_origdir)
        {

            # Check whether the /var/lib/systemimager link to
            # /csminstall/Linux/SIS directory
            my $target_dir = readlink($sis_origdir);
            if (   ($target_dir eq $sis_csmdir)
                || ($target_dir eq $sis_csmdir . "/"))
            {
                return 0;
            }
        }

        # Back the directory of /var/lib/systemimager to
        # /var/lib/systemimager.csmback and create a new link.
        NodeUtils->message('I', 'IMsgMOVE_DIRECTORY', $sis_origdir,
                           $sis_origdir_back);
        if (!rename($sis_origdir, $sis_origdir_back))
        {
            NodeUtils->message('E', 'EMsgERROR_MOVE_DIRECTORY', $sis_origdir,
                               $sis_origdir_back);
            return -1;
        }

        $cmd = "$::LN -fs $sis_csmdir $sis_origdir";
        $rc = NodeUtils->runcmd($cmd, 0);
        print $rc if $::VERBOSE;
        return $::RUNCMD_RC;
    }
    else
    {
        if (check_valid_sisdir($sis_origdir))
        {
            if (-d $sis_csmdir)
            {

                # Back the directory of /csminstall/Linux/SIS to
                # /csminstall/Linux/SIS.csmback.
                NodeUtils->message('I', 'IMsgMOVE_DIRECTORY', $sis_csmdir,
                                   $sis_csmdir_back);
                if (!rename($sis_csmdir, $sis_csmdir_back))
                {
                    NodeUtils->message('E', 'EMsgERROR_MOVE_DIRECTORY',
                                       $sis_csmdir, $sis_csmdir_back);
                    return -1;
                }
            }

            # Move the directory of /var/lib/systemimager to
            # /csminstall/Linux/SIS, and make symbol link for it.
            $cmd = "$::MOVE $sis_origdir $sis_csmdir";
            $rc = NodeUtils->runcmd($cmd, 0);
            print $rc if $::VERBOSE;
            if ($::RUNCMD_RC)
            {
                NodeUtils->message('E', 'EMsgERROR_MOVE_DIRECTORY',
                                   $sis_origdir, $sis_csmdir);
                return -1;
            }

            $cmd = "$::LN -fs $sis_csmdir $sis_origdir";
            $rc = NodeUtils->runcmd($cmd, 0);
            print $rc if $::VERBOSE;
            return $::RUNCMD_RC;
        }
    }

    return -1;
}

#--------------------------------------------------------------------------------

=head3	Main	

	Programmers note:

		Basically there are 2 conditions: AIX or Linux.
		If this is AIX, then the first big "if" will be done,
		otherwise, go to the other "if" InstallOSName eq Linux.

=cut

#--------------------------------------------------------------------------------

{    # main

    # initialize global variables
    &initialize;

    # parse the arguments
    &getArgs;

    my $runoption = "-1";

    if ($::VERBOSE) { $runoption = "0"; }

    # if backup data is available in /var/opt/csm/csmdata then copy it to
    # /tmp so that it is not removed, and then mv it back so that it is not
    # removed.
    if (-d "/var/opt/csm/csmdata")
    {
        my $cmd = "mv -f /var/opt/csm/csmdata /tmp/csmdata.uninstallms";
        NodeUtils->runcmd($cmd, -1);
    }

    # bad InstallOSName value
    if (   ($::ATTRS{'InstallOSName'} ne "Linux")
        && ($::ATTRS{'InstallOSName'} ne "AIX"))
    {
        NodeUtils->message('E1', 'EMsgUnsupportedOS');
    }

    #  AIX

    if ($::ATTRS{'InstallOSName'} eq "AIX")
    {

        # Remove the members of a Node Group
        NodeUtils->runcmd(
            "/usr/bin/chrsrc-api -i -s IBM.NodeGroup::\"MemberList!=''\"::\"MemberList::\"{}\"\"",
            $runoption, 0
            );
        if ($::RUNCMD_RC != 0)
        {
            NodeUtils->message('W', 'EMsgCannotRemoveNodegrpMembers');
        }

        # Before we remove the nodes, we need to see if the license has been
        # installed yet.  We can do this by checking to see if the "receipt"
        # file exists.  Their are two places we can check:
        # /var/opt/csm/1.3/tryandbuy/license/status.dat
        # or
        # /var/opt/csm/1.3/full/license/status.dat
        # where 1.3 is the csmversion.
        my $statusDir = "/var/opt/csm/";

        # now get the CSM version.  We only take the version and mod.
        # so 1.3.0.1 -> 1.3
        # and 1.3.2  -> 1.3
        # and 1.5.0  -> 1.5

        my $ver = $::ATTRS{'InstallCSMVersion'};
        $ver =~ /(\d+)\.(\d+)/;
        $ver = "$1.$2";
        $statusDir .= "$ver/";

        my $tabStatusFile  = $statusDir . "tryandbuy/license/status.dat";
        my $fullStatusFile = $statusDir . "full/license/status.dat";

        # if one of the above status files exist, then the license has been accepted.
        # this implies that there may be nodes defined.
        if ((-f $tabStatusFile) || (-f $fullStatusFile))
        {

            # Remove the  Node groups from the system
            NodeUtils->runcmd(
                        "/usr/bin/rmrsrc-api -i -s IBM.NodeGroup::\"Name!=''\"",
                        $runoption, 0);
            if ($::RUNCMD_RC != 0)
            {
                NodeUtils->message('W', 'EMsgCannotRemoveNodegrp');
            }

            # get the node list
            my $myresult = NodeUtils->listNodeAttrs([], "Hostname");
            foreach my $my_node (@$myresult)
            {
                push(@::My_NodeList, $my_node);
            }
            my $rm_cmd = "$::RMNODE";
            $rm_cmd .= " -v" if ($::VERBOSE);
            $rm_cmd .= " -u" if ($::opt_u);
            foreach my $my_node (@::My_NodeList)
            {

                # Running the rmnode command
                my $mycmd = "$rm_cmd $my_node";
                $myresult = NodeUtils->runcmd("$mycmd", $runoption);
                if ($::RUNCMD_RC != 0)
                {
                    NodeUtils->message('W', 'EMsgCANT_RUN_CMD', $mycmd);
                }
            }
        }    # the enclosed is only done if the lic has been accepted.

        # Now remove the CSM packages
        my ($my_package, $my_logfile, $my_cmd, $my_result);

        # remove the pre-defined-condresposes
        # this is done in csmserveruncfg

        # remove the CSM packages
        foreach $my_package (@::csm_uninstall_packages)
        {
            $my_cmd = "$::INSTALLPCMD -u $my_package";
            $my_result = NodeUtils->runcmd("$my_cmd", $runoption);
            if ($::RUNCMD_RC != 0)
            {
                NodeUtils->message('W', 'EMsgCANT_RUN_CMD', $my_cmd);
            }
        }

        # remove the RSCT packages
        foreach $my_package (@::rsct_uninstall_packages)
        {
            $my_cmd = "$::INSTALLPCMD -u $my_package";
            $my_result = NodeUtils->runcmd("$my_cmd", $runoption);
            NodeUtils->message('W', 'EMsgCANT_RUN_CMD', $my_cmd)
              if ($::RUNCMD_RC);
        }
    }

    # LINUX

    if ($::ATTRS{'InstallOSName'} eq "Linux")
    {

        # For Linux we just remove the CSM packages
        # We don't remove any nodes, because they will get removed with
        # the packages.

        # Exit if csm.director.agent is installed, because it has
        # a prereq on rsct.core.utils.
        NodeUtils->runcmd("$::RPMCMD -q csm.director.agent", -1);
        if ($::RUNCMD_RC == 0)
        {
            NodeUtils->message('I',  'IMsgUNINSTALLMS_NOT_UNINSTALLING');
            NodeUtils->message('E1', 'EMsgUNINSTALLMS_RUN_RMLCSEXT');
            exit 1;
        }

        # If -u option is used than than run rmnode command
        if ($::opt_u)
        {

            # get the node list
            my $myresult = NodeUtils->listNodeAttrs([], "Hostname");
            foreach my $my_node (@$myresult)
            {
                push(@::My_NodeList, $my_node);
            }
            my $rm_cmd = "$::RMNODE";
            $rm_cmd .= " -v" if ($::VERBOSE);
            $rm_cmd .= " -u" if ($::opt_u);
            foreach my $my_node (@::My_NodeList)
            {

                # Running the rmnode command
                my $mycmd = "$rm_cmd $my_node";
                $myresult = NodeUtils->runcmd("$mycmd", $runoption);
                if ($::RUNCMD_RC != 0)
                {
                    NodeUtils->message('W', 'EMsgCANT_RUN_CMD', $mycmd);
                }
            }
        }

        # remove the packages
        my (@uninstall_packages, $my_cmd, $my_package, $my_result);

        foreach (@::csm_uninstall_packages)
        {
            push @uninstall_packages, $_;
        }

        #don't remove rsct if rsct.basic is installed
        NodeUtils->runcmd("$::RPMCMD -q rsct.basic", -1);
        if ($::RUNCMD_RC == 0)
        {
            $::rsct_basic_Flg = 1;
        }
        else
        {

            #don't remove rsct if csm.client is installed
            NodeUtils->runcmd("$::RPMCMD -q csm.client", -1);
            if ($::RUNCMD_RC == 0)
            {
                $::csm_client_Flg = 1;
            }
            else
            {
                foreach (@::rsct_uninstall_packages)
                {
                    push @uninstall_packages, $_;
                }
            }
        }

        foreach $my_package (@uninstall_packages)
        {
            $my_cmd = "$::RPMCMD -q $my_package 2>&1 > /dev/null";
            $my_result = NodeUtils->runcmd("$my_cmd", $runoption);
            if ($::RUNCMD_RC == 0)
            {    # If it is installed, uninstall it
                $my_cmd = "$::RPMCMD -e $my_package";
                $my_result = NodeUtils->runcmd("$my_cmd", $runoption);
                NodeUtils->message('W', 'EMsgCANT_RUN_CMD', $my_cmd)
                  if $::RUNCMD_RC;
            }
        }

    }

    # Both AIX and Linux

    # Is rsct.core installed?
    my $rsct_pkg = "rsct.core";
    my $cmd      = "$::RPMCMD -q $rsct_pkg 2>&1 > /dev/null";
    NodeUtils->runcmd("$cmd", -1);

    # Clean the rmsr table if rsct.core is still installed
    if ($::RUNCMD_RC == 0)
    {

        # not adding messages - runcmd should show in the log.

        my $RMSRTBL = "/usr/bin/rmsrtbl-api";

        # ManagedNode
        $cmd = "$RMSRTBL /IBM/ManagedNode/Resources";
        NodeUtils->runcmd("$cmd", 0);

        # DmsCtrl
        $cmd = "$RMSRTBL /IBM/DmsCtrl/Resources";
        NodeUtils->runcmd("$cmd", 0);

        # NodeGroup
        $cmd = "$RMSRTBL /IBM/NodeGroup/Resources";
        NodeUtils->runcmd("$cmd", 0);
    }

    # remove the log files package
    foreach my $my_logfile (@::csm_logfilelist)
    {
        &remove_files_dir($my_logfile);
    }

    # Display a list of the files, Directories and packages that were not
    # uninstalled (because they were not installed by installms)

    NodeUtils->message('I', 'IMsgDidnotRemoveDir',
                       join(', ', @::csmUninstallList_Directories));

    NodeUtils->message('I', 'IMsgDidnotRemovePkgs',
                       join(', ', @::csmUninstallList_Packages));

    NodeUtils->message('I', 'IMsgDidnotUninstallOpenSrcPkgs');

    if ($::rsct_basic_Flg == 1 || $::csm_client_Flg == 1)
    {
        NodeUtils->messageFromCat('csmInstall.cat', $::MSGMAPPATH, 'csminstall',
                                  'I', 'IMsgDidnotUninstallRsct');
    }

    NodeUtils->message('I', 'IMsgDidnotUnconfigureRemoteShellServer');

    # put csmdata back
    if (-d "/tmp/csmdata.uninstallms")
    {
        NodeUtils->runcmd("mkdir -p /var/opt/csm/", -1);
        NodeUtils->runcmd("mv -f /tmp/csmdata.uninstallms /var/opt/csm/csmdata",
                          -1);
    }

    exit 0;
}
